package com.woniu.service.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.woniu.dto.*;
import com.woniu.entity.*;
import com.woniu.mapper.*;
import com.woniu.publisher.CustomPublisher;
import com.woniu.publisher.TopicPublisher;
import com.woniu.service.OrderService;
import com.woniu.service.ProductService;
import com.woniu.util.*;
import com.woniu.vo.OrderVo;
import com.yomahub.liteflow.core.FlowExecutor;
import com.yomahub.liteflow.flow.LiteflowResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.Duration;
import java.util.*;

@Service
@Slf4j
public class OrderServiceImpl implements OrderService {
    @Resource
    private OrderMapper orderMapper;
    @Resource
    private OrderItemMapper orderItemMapper;
    @Resource
    private CustomerMapper customerMapper;
    @Resource
    private ProductMapper productMapper;


    @Override
    public ResponseUtil findSearchOrders(OrderSearchDTO orderSearchDTO) {
        // 1. 启动分页
        PageHelper.startPage(orderSearchDTO.getPageNum(), orderSearchDTO.getPageSize());

        // 2. 执行查询
        // PageHelper 会拦截这个查询
        List<Order> orderList = orderMapper.findSearchOrders(orderSearchDTO);

        // 3. 使用 PageInfo 包装查询结果，获取分页信息 (包括 total)
        PageInfo<Order> pageInfo = new PageInfo<>(orderList);

        return ResponseUtil.get(ResponseEnum.OK, pageInfo);
    }

    @Override
    public ResponseUtil findDeleteById(String orderId) {
        Integer result = orderMapper.findDeleteById(orderId);
        return result > 0 ? ResponseUtil.get(ResponseEnum.OK)
                : ResponseUtil.get(ResponseEnum.FAIL);
    }

    @Override
    public ResponseUtil findPaidUnshippedOrders() {
        List<OrderVo> orders = orderMapper.findPaidUnshippedOrders();
        return ResponseUtil.get(ResponseEnum.OK, orders);
    }

    @Resource
    private ProductService productService;
    @Override
    public ResponseUtil getOrderForEdit(String orderId) {
        OrderVo orderVo = orderMapper.findById(orderId);
        if (orderVo == null) {
            return ResponseUtil.get(ResponseEnum.FAIL, "订单不存在");
        }

        Integer status = orderVo.getStatus();
        // 允许状态为 0 或 -1
        if (status == null || (status != 0 && status != -1)) {
            return ResponseUtil.get(ResponseEnum.FAIL, "只有未审批或草稿状态的订单才能编辑");
        }

        List<OrderItem> orderItems = orderItemMapper.findOrderDetail(orderId);
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("order", orderVo);
        resultMap.put("orderItems", orderItems); // 建议判空处理，见下方说明
        productService.findAll2();
        return ResponseUtil.get(ResponseEnum.OK, resultMap);
    }

    @Override
    @Transactional
    public ResponseUtil editOrder(OrderEditDTO orderEditDTO) {
        String orderId = orderEditDTO.getOrderId();

        // 1. 查询原订单
        OrderVo orderVo = orderMapper.findById(orderId);
        if (orderVo == null) {
            return ResponseUtil.get(ResponseEnum.FAIL, "订单不存在");
        }

        // 2. 判断是否可编辑：0=待审批，-1=已拒绝
        if (!(orderVo.getStatus().equals(0) || orderVo.getStatus().equals(-1))) {
            return ResponseUtil.get(ResponseEnum.FAIL, "只有未审批或已拒绝的订单才能编辑");
        }

        // 3. 获取新订单项（要插入的商品）
        List<OrderItem> newItems = orderEditDTO.getOrderItems();
        if (newItems == null || newItems.isEmpty()) {
            return ResponseUtil.get(ResponseEnum.FAIL, "新订单项不能为空");
        }

        // Redis Key 定义
        String redisKey = ConstantUtil.REDIS_PRODUCT_KEY;

        // 前置库存校验（只读，不修改）
        List<String> notEnoughItems = new ArrayList<>();
        for (OrderItem item : newItems) {
            Integer productId = item.getProductId();
            Integer buyNum = item.getBuyNum();

            // 从 Redis 获取 Product
            String fieldKey = ConstantUtil.REDIS_PRODUCT_KEY + productId;
            Product product = (Product) redisTemplateInit.opsForHash().get(redisKey, fieldKey);

            if (product == null) {
                notEnoughItems.add("商品【" + item.getName() + "】信息未找到，请稍后重试");
                continue;
            }

            BigDecimal currentStock = product.getStock();
            BigDecimal buyNumDecimal = BigDecimal.valueOf(buyNum);

            if (currentStock == null || currentStock.compareTo(buyNumDecimal) < 0) {
                notEnoughItems.add("商品【" + item.getName() + "】库存不足，当前库存：" + currentStock + "，需求数量：" + buyNum);
            }
        }

        // 如果有库存不足的商品，直接返回错误
        if (!notEnoughItems.isEmpty()) {
            String errorMsg = String.join("\n", notEnoughItems);
            return ResponseUtil.get(ResponseEnum.FAIL, errorMsg);
        }

        // 4. 查询原订单项（用于归还库存）
        List<OrderItem> originalItems = orderItemMapper.findOrderDetail(orderId);

        // 5. 归还原订单的库存（编辑前释放旧库存）
        if (originalItems != null && !originalItems.isEmpty()) {
            for (OrderItem item : originalItems) {
                Long productId = Long.valueOf(item.getProductId());
                String fieldKey = ConstantUtil.REDIS_PRODUCT_KEY + productId;

                // 第一次删除缓存（先删，防止旧缓存干扰）
                redisTemplateInit.delete(redisKey);

                // 更新数据库：归还库存
                int result = productMapper.increaseStock(productId, item.getBuyNum());
                if (result <= 0) {
                    throw new RuntimeException("归还商品【" + item.getName() + "】库存失败");
                }

                // 延迟一段时间（例如 500ms），等待可能的并发读请求完成
                try {
                    Thread.sleep(500); // 可配置为常量或参数
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    // 日志记录
                }

                // 第二次删除缓存（防止在更新数据库期间又有旧缓存被重建）
                redisTemplateInit.delete(redisKey);
            }
        }

        // 6. 更新订单主表
        Order updateOrder = new Order();
        BeanUtils.copyProperties(orderEditDTO, updateOrder);
        Integer orderUpdateResult = orderMapper.update(updateOrder);
        if (orderUpdateResult <= 0) {
            throw new RuntimeException("更新订单主表失败");
        }

        // 7. 删除原订单项
        Integer deleteItemsResult = orderItemMapper.delete(orderId);
        if (deleteItemsResult < 0) {
            throw new RuntimeException("删除原订单项失败");
        }

        // 8. 插入新订单项（仅插入订单项，不扣库存）
        Date now = new Date();
        for (OrderItem item : newItems) {
            item.setOrderId(orderId);
            item.setCreateTime(now);
        }
        Integer insertResult = orderItemMapper.batchInsertOrderItems(newItems);
        if (insertResult <= 0) {
            throw new RuntimeException("插入新订单项失败");
        }

        return ResponseUtil.get(ResponseEnum.OK, "订单编辑成功，库存尚未扣减");
    }


    @Resource
    private ProcurePlanMapper procurePlanMapper;

    /**
     * 添加订单
     * 客户信息验证：若客户不存在，提示触发表单验证（实际可结合前端做更完善的客户信息录入验证）。
     * 订单项验证：确保至少有一个订单项，且次品商品采购数量不超过库存上限。
     * 订单添加：先插入订单主表，再插入订单项，订单初始状态为 “不纳入采购计划，待审批”。
     *
     * @param orderAddDTO
     * @return
     */
    @Override
    public ResponseUtil addOrder(OrderAddDTO orderAddDTO) throws InterruptedException {
        // 客户信息验证
        Customer customer = customerMapper.findById(orderAddDTO.getCustomerId());
        if (customer == null) {
            return ResponseUtil.get(ResponseEnum.FAIL, "客户信息不存在，请先完善客户信息");
        }

        // Redis Key 定义
        String redisKey = ConstantUtil.REDIS_PRODUCT_KEY;

        // === 阶段一：检查库存，收集缺货商品，生成采购计划 ===
        List<ProcurePlan> procurePlans = new ArrayList<>();
        StringBuilder shortageMsg = new StringBuilder("以下商品库存不足，已生成采购计划，请等待采购入库后重新下单：\n");

        // 先遍历所有订单项，检查库存（从 Redis 读取）
        for (OrderItemAddDTO itemAddDTO : orderAddDTO.getOrderItems()) {
            Integer productId = itemAddDTO.getProductId();
            String fieldKey = ConstantUtil.REDIS_PRODUCT_KEY + productId;

            // ✅ 优先从 Redis 获取商品
            Product product = (Product) redisTemplateInit.opsForHash().get(redisKey, fieldKey);

            if (product == null) {
                log.warn("商品【{}】未命中缓存，回源查询数据库", productId);
                // 回源查数据库
                product = productMapper.findByProductId(productId);
                if (product == null) {
                    return ResponseUtil.get(ResponseEnum.FAIL, "商品ID为" + productId + "的商品不存在");
                }
            }

            BigDecimal buyNum = BigDecimal.valueOf(itemAddDTO.getBuyNum());
            if (buyNum.compareTo(product.getStock()) > 0) {
                BigDecimal needToProcure = buyNum
                        .subtract(product.getStock())
                        .add(BigDecimal.valueOf(100)); // 额外采购 100 件

                ProcurePlan procurePlan = new ProcurePlan();
                procurePlan.setProcureId("PROC" + UUID.randomUUID().toString().substring(0, 8));
                procurePlan.setProductId(productId);
                procurePlan.setNum(needToProcure);
                procurePlan.setStatus(0);
                procurePlan.setPrice(product.getPrice());
                procurePlan.setType("1"); // 成品
                procurePlan.setOrderId(null);

                procurePlans.add(procurePlan);
                shortageMsg.append("【").append(product.getName())
                        .append("】需采购 ").append(needToProcure)
                        .append(" 件（当前库存：").append(product.getStock()).append("）\n");
            }
        }

        // 如果有库存不足的情况，生成采购计划并终止订单创建
        if (!procurePlans.isEmpty()) {
            for (ProcurePlan plan : procurePlans) {
                procurePlanMapper.add(plan);
            }
            return ResponseUtil.get(ResponseEnum.FAIL, shortageMsg.toString());
        }

        // === 阶段二：所有商品库存充足，正常创建订单 ===

        // 生成订单号
        SnowflakeIdGenerator idWorker = new SnowflakeIdGenerator();
        long orderId = idWorker.nextId();
        String orderIdStr = "ORD" + orderId;

        // 订单项验证
        if (orderAddDTO.getOrderItems() == null || orderAddDTO.getOrderItems().isEmpty()) {
            return ResponseUtil.get(ResponseEnum.FAIL, "订单项至少得有一项");
        }

        List<OrderItem> orderItems = new ArrayList<>();
        BigDecimal totalPrice = BigDecimal.ZERO;
        Map<Long, Integer> productIdToBuyNumMap = new HashMap<>();

        for (OrderItemAddDTO itemAddDTO : orderAddDTO.getOrderItems()) {
            Integer productId = itemAddDTO.getProductId();
            String fieldKey = ConstantUtil.REDIS_PRODUCT_KEY + productId;

            Product product = (Product) redisTemplateInit.opsForHash().get(redisKey, fieldKey);
            if (product == null) {
                product = productMapper.findByProductId(productId);
                if (product == null) {
                    return ResponseUtil.get(ResponseEnum.FAIL, "商品【" + productId + "】不存在");
                }
            }

            if (itemAddDTO.getBuyNum() == null || itemAddDTO.getBuyNum() <= 0) {
                return ResponseUtil.get(ResponseEnum.FAIL, "商品【" + product.getName() + "】购买数量必须大于0");
            }

            OrderItem orderItem = new OrderItem();
            BeanUtils.copyProperties(itemAddDTO, orderItem);
            orderItem.setProductId(product.getProductId());
            orderItem.setName(product.getName());
            orderItem.setPrice(product.getPrice());
            orderItem.setBuyNum(itemAddDTO.getBuyNum());

            BigDecimal itemTotal = product.getPrice().multiply(BigDecimal.valueOf(itemAddDTO.getBuyNum()));
            orderItem.setSumPrice(itemTotal);

            orderItems.add(orderItem);
            totalPrice = totalPrice.add(itemTotal);
            productIdToBuyNumMap.put(Long.valueOf(productId), itemAddDTO.getBuyNum());
        }

        // 创建订单主表
        Order order = new Order();
        order.setOrderId(orderIdStr);
        order.setCustomerId(orderAddDTO.getCustomerId());
        order.setTotalPrice(totalPrice);
        order.setStatus(0); // 待审批
        order.setCreateTime(new Date());
        order.setAddressId(orderAddDTO.getAddressId());

        // 设置订单项
        Date now = new Date();
        for (OrderItem orderItem : orderItems) {
            orderItem.setOrderId(orderIdStr);
            orderItem.setCreateTime(now);
        }

        // 异步发送订单（如使用消息队列）
        OrderDTO orderDTO = new OrderDTO(order, orderItems);
        String jsonString = JSON.toJSONString(orderDTO);
        topicPublisher.send(jsonString, ConstantUtil.ROUTING_KEY_ORDER);

        // === 扣减库存 + 延迟双删缓存 ===
        for (Map.Entry<Long, Integer> entry : productIdToBuyNumMap.entrySet()) {
            Long productId = entry.getKey();
            Integer buyNum = entry.getValue();
            String fieldKey = ConstantUtil.REDIS_PRODUCT_KEY + productId;

            // 第一次删除缓存
            redisTemplateInit.delete(redisKey);

            // 更新数据库：扣减库存
            int result = productMapper.reduceStock(productId, buyNum);
            if (result <= 0) {
                throw new RuntimeException("商品【" + productId + "】扣库存失败");
            }

            // 延迟 500ms
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }

            // 第二次删除缓存
            redisTemplateInit.delete(redisKey);
        }

        // 防重复提交
        redisTemplateInit.opsForValue().set(ConstantUtil.REDIS_ORDER + order.getOrderId(), order.getOrderId(), Duration.ofHours(1));

        // 发送延迟取消消息（15分钟后未支付则取消）
//        try {
//            customPublisher.send(order.getOrderId(), ConstantUtil.RABBIT_TTL);
//        } catch (Exception e) {
//            log.warn("发送延迟取消消息失败，orderId={}", order.getOrderId(), e);
//        }

        return ResponseUtil.get(ResponseEnum.OK, "订单创建成功，15分钟未付款取消订单");
    }

    @Resource
    private CustomPublisher customPublisher;

    /**
     * 订单审批
     *
     * @param orderId
     * @return
     */
    @Override
    public ResponseUtil submitApproval(String orderId) {
        // 1. 查询订单是否存在
        Order order = orderMapper.getById(orderId);
        if (order == null) {
            return ResponseUtil.get(ResponseEnum.FAIL, "订单不存在");
        }

        // 2. 检查订单状态是否为“待审批”（status = 0） “审批失败”（status = -1）
        Integer status = order.getStatus();
        // 只有状态为 0（待审批）或 -1（审批失败）时，才允许审批
        if (status == null || (status != 0 && status != -1)) {
            return ResponseUtil.get(ResponseEnum.FAIL, "只有待审批或审批失败的订单才能进行审批");
        }

        // 3. 构建上下文
        OrderContext context = new OrderContext();
        context.setOrderId(orderId);
        context.setStatus(order.getStatus());

        // 4. 执行 LiteFlow 流程
        LiteflowResponse response = flowExecutor.execute2Resp("orderFlow", "myBizTag", context);

        // 5. 判断流程执行结果
        if (context.isApprovalSuccess()) {
            return ResponseUtil.get(ResponseEnum.OK, "订单审批通过");
        } else {
            String errorMsg = context.getErrorMsg();
            return ResponseUtil.get(ResponseEnum.FAIL, errorMsg != null ? errorMsg : "审批失败");
        }
    }

    private static final int EXPORT_PAGE_SIZE = 1000;

    @Override
    public List<OrderExportDTO> findExportOrders(int pageIndex) {
        int offset = pageIndex * EXPORT_PAGE_SIZE;
        return orderMapper.findExportOrders(offset, EXPORT_PAGE_SIZE);
    }

    @Override
    public long countTotalOrders() {
        return orderMapper.countTotalOrders();
    }

    @Override
    public ResponseUtil editOrderReturn(Order order) {
        int result = orderMapper.updateOrderStatus(order.getOrderId(), 7);
        return result > 0 ? ResponseUtil.get(ResponseEnum.OK)
                : ResponseUtil.get(ResponseEnum.FAIL);
    }

    @Override
    public ResponseUtil getFullOrderDetail(String orderId) {
        Map<String, Object> baseWithAddress = orderMapper.findBaseWithAddressById(orderId);
        if (baseWithAddress == null || baseWithAddress.isEmpty()) {
            return ResponseUtil.get(ResponseEnum.FAIL, "订单不存在");
        }
        List<OrderItem> orderItems = orderItemMapper.findOrderDetail(orderId);
        Map<String, Object> result = new HashMap<>();
        result.put("order", baseWithAddress);
        result.put("orderItems", orderItems);
        return ResponseUtil.get(ResponseEnum.OK, result);
    }

    @Override
    public ResponseUtil findSearchOrdersReturn(OrderSearchDTO orderSearchDTO) {
        // 1. 启动分页
        PageHelper.startPage(orderSearchDTO.getPageNum(), orderSearchDTO.getPageSize());

        // 2. 执行查询
        // PageHelper 会拦截这个查询
        List<Order> orderList = orderMapper.findReturnSearchOrders(orderSearchDTO);

        // 3. 使用 PageInfo 包装查询结果，获取分页信息 (包括 total)
        PageInfo<Order> pageInfo = new PageInfo<>(orderList);

        return ResponseUtil.get(ResponseEnum.OK, pageInfo);
    }

    @Resource
    private RedisTemplate redisTemplateInit;
    @Resource
    private TopicPublisher topicPublisher;
    @Resource
    private FlowExecutor flowExecutor;

}

